using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.ComponentModel;
using Microsoft.VisualBasic;

namespace ComprUtils 
{
  public class UnRar : BackgroundWorker, ComprUtils.IUnpack
  {
    public UnRar()
    {
      _uRAR.CmtBuf = string.Empty.PadLeft(16384, ' ');
      _uRAR.CmtBufSize = 16384;
      _uRAR.OpenMode = RarOpenMode.RAR_OM_LIST;
      _uHeader.CmtBuf = string.Empty.PadLeft(16384, ' ');
      _uHeader.CmtBufSize = 16384;
    }
    RARHeaderDataEx _uHeader = new RARHeaderDataEx();
    RAROpenArchiveDataEx _uRAR = new RAROpenArchiveDataEx();
    IntPtr lHandle; int iStatus, iStatus2,_iCount;
    string _rarFilename;
    string _currFile;

    public string CurrFile
    {
      get { return _currFile; }
    }

    public string PackFilename
    {
      get { return _rarFilename; }
      set { _rarFilename = value; }
    }
    string _targetDir;
    public string TargetDir
    {
      get { return _targetDir; }
      set { _targetDir = value; }
    }

    public List<string> GetListFromPack()
    {
      List<string> list = new List<string>();
      _uRAR.OpenMode = RarOpenMode.RAR_OM_LIST;
      lHandle = UnRarInterop.RAROpenArchiveEx(ref _uRAR);
      while (iStatus == 0)
      {
        iStatus = UnRarInterop.RARReadHeaderEx(lHandle, ref _uHeader);
        list.Add(_uHeader.FileName);
        Console.WriteLine(_uHeader.FileName);
        iStatus2 = UnRarInterop.RARProcessFile(lHandle, RarOperations.RAR_OP_TEST, _targetDir, null);
      }
      iStatus = UnRarInterop.RARCloseArchive(lHandle);
      return list;
    }

    public void ExtractPack()
    {
      _uRAR.ArcName = this.PackFilename;
      List<string> list = GetListFromPack();
      _iCount = 0;
      ReportProgress(0);
      _uRAR.OpenMode = RarOpenMode.RAR_OM_EXTRACT;
      lHandle = UnRarInterop.RAROpenArchiveEx(ref _uRAR);
      while (iStatus == 0)
      {
        iStatus = UnRarInterop.RARReadHeaderEx(lHandle, ref _uHeader);
        _currFile = Path.Combine(PackFilename, _uHeader.FileName);
        UnRarInterop.RarCallbackProcDelegate delOfProc =
          new UnRarInterop.RarCallbackProcDelegate(RarCallbackProc);
        UnRarInterop.RARSetCallback(lHandle, delOfProc, lHandle);
        RarOperations op = File.Exists(_currFile) ?
          RarOperations.RAR_OP_SKIP: RarOperations.RAR_OP_EXTRACT;
        iStatus2 = UnRarInterop.RARProcessFile(lHandle, op, _targetDir, null);
        ReportProgress(Math.Min(100, Convert.ToInt32(_iCount * 100 / list.Count)), _uHeader.FileName);
        _iCount++;
      }
      ReportProgress(100);
      iStatus = UnRarInterop.RARCloseArchive(lHandle);
    }

    protected override void OnDoWork(DoWorkEventArgs e)
    {
      ExtractPack();
      base.OnDoWork(e);
    }


int RarCallbackProc(RarCallbackMessages msg,IntPtr UserData, IntPtr P1, int P2)
{
  int Result = 0;
  switch(msg)
  {
    case RarCallbackMessages.UCM_CHANGEVOLUME:
      if (P2 == (int)RarVol.RAR_VOL_ASK) 
      {
        //CString Info; Info.Format("A volume %s is required, terminate now", ApiGetFileName((char*)P1));
      }
      if (P2 == (int)RarVol.RAR_VOL_NOTIFY)
      {
        // 			CString Path=(char *)P1;
        // pThis->Update_Gui_Info(_T("-Unpacking ") + ApiGetFileName(Path));
      }
        break;
    case RarCallbackMessages.UCM_PROCESSDATA:
        //lKBytesDone += P2; // bytes written so far
        Result = 1;
        break;
      case RarCallbackMessages.UCM_NEEDPASSWORD:
        string pass = Interaction.InputBox("Enter Password to decompress " + _uHeader.FileName, "RAR protected file", "", 500, 300);
        IntPtr lHandle = UserData;
        UnRarInterop.RARSetPassword(lHandle, pass);
        break;
      default:
        Result = 1;
      break;
  }
  return Result;
  }

  } // end class
}
